﻿#ifndef PLUGINMANAGER_H
#define PLUGINMANAGER_H

#include <QObject>
#include <QReadLocker>
#include <QVector>
#include "Extensionsystem_Global.h"

namespace CVV
{

namespace Infrastructure
{

namespace ExtensionSystem
{

namespace Internal { class PluginManagerPrivate; }
class PluginSpec;
/**
 * @brief The PluginManager class
 * 插件管理类
 */
class EXTENSIONSYSTEM_EXPORT PluginManager : public QObject
{
    Q_OBJECT
public:
    PluginManager();
    ~PluginManager() override;

    static PluginManager *instance();

    /***********************************************************************
     *  @function addObject
     *  @brief 新建插件对象
     *  @param 插件对象
    ***********************************************************************/
    static void addObject(QObject *obj);
    /***********************************************************************
     *  @function removeObject
     *  @brief  移除对象
     *  @param  obj 插件对象
    ***********************************************************************/
    static void removeObject(QObject *obj);
    /***********************************************************************
     *  @function removeObject
     *  @brief  清除插件对象
    ***********************************************************************/
    static void clearPlugin();
    /***********************************************************************
     *  @function allObjects
     *  @brief  获取所有插件对象
     *  @return 插件对象数组
    ***********************************************************************/
    static QVector<QObject *> allObjects();
    /***********************************************************************
     *  @function listLock
     *  @brief 获取读写锁指针
     *  @return 读写锁指针
    ***********************************************************************/
    static QReadWriteLock *listLock();
    /***********************************************************************
     *  @function getObjectByName
     *  @brief 通过插件名获取插件对象
     *  @param  插件名称
     *  @return  插件对象
    ***********************************************************************/
    static QObject *getObjectByName(const QString &name);

    /**
     * @brief getPluginNameByCode 根据code获取插件名
     * @param code
     * @return
     */
    static QString getPluginNameByCode(const QString &code);

    /**
     * @brief getPluginSpecByCode 根据code获取插件配置
     * @param code
     * @return
     */
    static PluginSpec* getPluginSpecByCode(const QString &code);


    // Plugin operations
    /**
     * @brief setPluginPaths
     * 1.设置插件路径
     * @param paths
     *
     */
    static void setPluginPaths(const QStringList &paths);
    /**
     * @brief loadQueue
     * 2.加载插件规格信息
     * @return
     */
    static QVector<PluginSpec *> loadQueue();
    /**
     * @brief loadPlugins
     * 3.加载插件
     */
    static void loadPlugins();

    /**
     * @brief pluginIID
     * 获取插件ID
     * @return
     */
    static QString pluginIID();
    /**
     * @brief setPluginIID
     * 设置插件ID
     * @param iid
     */
    static void setPluginIID(const QString &iid);
    /**
     * @brief pluginPaths
     * 获取插件路径
     * @return
     */
    static QStringList pluginPaths();
    /**
     * @brief plugins
     * @return
     */
    static const QVector<PluginSpec *> plugins();
    //插件参数管理
    static const QMap<QString,QJsonArray> pluginParams();
    static void addPluginParam(QString pluginCode,QJsonArray array);
    static void removePluginParam(QString pluginCode);
signals:
    /***********************************************************************
     *  @signal objectAdded
     *  @brief 添加插件对象之后发出信号
     *  @param  插件对象
    ***********************************************************************/
     void objectAdded(QObject *obj);
     /***********************************************************************
     *  @signal aboutToRemoveObject
     *  @brief 移除插件对象之后发出信号
     *  @param 插件对象
    ***********************************************************************/
     void aboutToRemoveObject(QObject *obj);
public:
     /***********************************************************************
     *  @function getObject
     *  @brief 获取插件模板函数
     *  @return 返回插件对象
    ***********************************************************************/
     template <typename T> static T *getObject()
     {
         QReadLocker lock(listLock());
         const QVector<QObject *> all = allObjects();
         for (QObject *obj : all) {
             if (T *result = qobject_cast<T *>(obj))
                 return result;
         }
         return nullptr;
     }
     /***********************************************************************
     *  @function getObject
     *  @brief 获取插件对象模板
     *  @return
    ***********************************************************************/
     template <typename T, typename Predicate> static T *getObject(Predicate predicate)
     {
         QReadLocker lock(listLock());
         const QVector<QObject *> all = allObjects();
         for (QObject *obj : all) {
             if (T *result = qobject_cast<T *>(obj))
                 if (predicate(result))
                     return result;
         }
         return 0;
     }
protected:
     friend class Internal::PluginManagerPrivate;
};

}

}

}
#endif // PLUGINMANAGER_H
